home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
726-750
/
729
/
ff
/
source
/
ff.c
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
35KB
|
1,337 lines
/***************************************************************************/
/* FindFile */
/* Version 1.01 */
/* August 30, 1992 */
/* */
/* This is a file-find utility with a 2.0-style GadTools interface. It */
/* doesn't support the CLI, although it can be run from the CLI; it is */
/* meant as a Workbench utility. */
/* */
/* This program is Copyright ©1992 by Dave Schreiber, All Rights Reserved. */
/* This program may not be sold for more than a small copying and shipping */
/* and handling fee, except by written permission of Dave Schreiber. */
/* */
/* To compile, type: */
/* lmk */
/* */
/* Version List: */
/* 1.01 - Changed the default wildcard from '*' to '#?' (since '*' */
/* needs to be explicitly turned on under Workbench 2.04 and not */
/* everyone has it turned on). */
/* August 30, 1992 */
/* 1.00 - First release (August 27, 1992) */
/* */
/***************************************************************************/
/*System headers*/
#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <utility/tagitem.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <libraries/asl.h>
#include <libraries/iffparse.h>
#include <workbench/workbench.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/gadtools.h>
#include <proto/asl.h>
#include <proto/iffparse.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/wb.h>
/*Program-specific headers*/
#include "FF.h"
#include "GUI.h"
#include "Lists.h"
/*SAS/C V5.10 doesn't have these (2.04) function calls in it's copy of*/
/*amiga.lib, so these are necessary*/
#pragma libcall DOSBase ParsePatternNoCase 3C6 32103
#pragma libcall DOSBase MatchPatternNoCase 3CC 2102
/*All the libraries we need*/
struct Library *IntuitionBase,*GfxBase,*GadToolsBase,*AslBase,
*WorkbenchBase,*IFFParseBase;
/*Flags for user settings*/
BOOL Links=FALSE; /*Recur into linked directories?*/
BOOL Recur=TRUE; /*Recur at all?*/
BOOL Wildcards=TRUE; /*Treat the 'Search For:' field as having wildcards?*/
/*The linked list of files*/
struct List *fileList=NULL;
/*The linked list of a file's path components*/
struct List *dirList=NULL;
/*The message port for the AppWindow*/
struct MsgPort *appMsgPort=NULL;
/*This holds the AppWindow data*/
struct AppWindow *appWdw=NULL;
/*The ordinal number (in the filelist) of the current filename*/
ULONG currentFilename=~0;
/*This contains the four pointer images that are animated during a find*/
/*They are not in proper "pointer" format, and must be interleaved and put*/
/*into pointerData, below. This is done in setupPointerBuffers()*/
USHORT PointerImageData[4][26] =
{
{
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xC000,0x01C0,0x1FC0,
0xFC00,0xC000,0x01C0,0x1FC0,0xFC00,0xC000,0x01C0,0x1FC0,
0xFC00,0xC000
},
{
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0x01C0,0x1FC0,0xFC00,
0xC000,0x01C0,0x1FC0,0xFC00,0xC000,0x01C0,0x1FC0,0xFC00,
0xC000,0x01C0
},
{
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0x1FC0,0xFC00,0xC000,
0x01C0,0x1FC0,0xFC00,0xC000,0x01C0,0x1FC0,0xFC00,0xC000,
0x01C0,0x1FC0
},
{
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,
0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFFC0,0xFC00,0xC000,0x01C0,
0x1FC0,0xFC00,0xC000,0x01C0,0x1FC0,0xFC00,0xC000,0x01C0,
0x1FC0,0xFC00
}
};
USHORT chip pointerData[4][30];
/*This keeps track of what 'frame' the pointer 'animation' is at*/
UBYTE pointerCount=0;
/*The version string. Do a 'version FF' to display it*/
char *version="$VER: FindFile V1.01 (30.8.92)";
ULONG numFiles;
/*****************************************************************************/
/* The first second contains the kernel of file-finding code */
/*****************************************************************************/
void _main(void)
{
char Pattern[256];
char Directory[256];
FindStat result=FIND_CONTINUE;
/*Copy and interleave the pointer image data*/
setupPointerBuffers();
/*Open all the libraries that we need*/
IntuitionBase=(struct Library *)OpenLibrary("intuition.library",37L);
GfxBase=(struct Library *)OpenLibrary("graphics.library",37L);
AslBase=(struct Library *)OpenLibrary("asl.library",37L);
GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",37L);
WorkbenchBase=(struct Library *)OpenLibrary("workbench.library",37L);
IFFParseBase=(struct Library *)OpenLibrary("iffparse.library",37L);
/*If any of them didn't open, abort*/
if(IntuitionBase==NULL || GfxBase==NULL || AslBase==NULL ||
GadToolsBase==NULL || IFFParseBase==NULL)
cleanup(100);
/*Get the visual info, etc.*/
if(SetupScreen()==0)
{
/*Open the window*/
if(OpenProject0Window()==0)
{
/*Create the AppWindow message port and, if successful, make*/
/*the window into an AppWindow*/
if((appMsgPort=CreateMsgPort())!=NULL)
appWdw=(struct AppWindow *)AddAppWindowA(1,0,Project0Wnd,
appMsgPort,NULL);
/*Loop until the user tells us to quit*/
/*getUserSelections() either returns FALSE, in which case we*/
/*quit, or TRUE, in which case we search*/
while((result!=FIND_CLOSE) && getUserSelections())
{
/*Get the 'Search for' string*/
strcpy(Pattern,((struct StringInfo *)
(Project0Gadgets[GD_Pattern]->SpecialInfo))->Buffer);
/*If there is no pattern or search string, print an error*/
if(Pattern[0]==0)
printError("Please enter a search pattern or name",NULL,NULL);
else /*Otherwise, do the search*/
{
/*There is no current filename*/
currentFilename=~0;
/*Create the 'busy' pointer*/
setBusyPointer();
/*We don't want to be bothered with AppWindow messages while*/
/*searching*/
if(appWdw!=NULL)
RemoveAppWindow(appWdw);
/*Delete an old file list, if one exists, and initialize a*/
/*fresh list*/
initFileList();
/*Disable all the gadgets that can be disabled, but enable */
/*the 'Stop' gadget*/
disableWindowGadgets();
/*Get the 'Search for' string*/
strcpy(Pattern,((struct StringInfo *)
(Project0Gadgets[GD_Pattern]->SpecialInfo))->Buffer);
/*Get the 'Directory' string*/
strcpy(Directory,((struct StringInfo *)
(Project0Gadgets[GD_Dir]->SpecialInfo))->Buffer);
numFiles=0;
/*And do the search*/
result=findFiles(Directory,Pattern,Recur);
/*The search is finished at this point, so enable all window*/
/*gadgets except for the Stop gadget, which is disabled*/
enableWindowGadgets();
/*Restore the old pointer*/
restorePointer();
/*Reset the AppWindow, if it existed in the first place*/
if(appMsgPort!=NULL)
appWdw=(struct AppWindow *)AddAppWindowA(1,0,Project0Wnd,
appMsgPort,NULL);
}
/*And loop back for another round...*/
}
/*The user wants to quit, so delete the AppWindow if it was created*/
if(appWdw!=NULL)
{
RemoveAppWindow(appWdw);
DeleteMsgPort(appMsgPort);
}
/*Delete the file and directory lists, if any exist*/
deleteFileList();
deleteDirList();
/*Close the window*/
CloseProject0Window();
}
/*Delete the visual info, etc.*/
CloseDownScreen();
/*Close libraries and exit with no errors*/
cleanup(0);
}
}
/*This is the interface between the main part of the program and the*/
/*recursive function that actually finds files.*/
FindStat findFiles(char *startingDir,char *pattern,BOOL recur)
{
char patResult[516];
BPTR fileLock;
UWORD c;
FindStat result=FIND_CONTINUE;
/*Clear the buffer that will hold the working pattern*/
for(c=0;c<516;c++)
patResult[c]=0;
/*If the user specified that the 'Search For' string didn't contain*/
/*a literal, create a working pattern from the given pattern*/
if(Wildcards)
ParsePatternNoCase(pattern,patResult,256);
else
/*Otherwise, just use the string as is*/
strcpy(patResult,pattern);
/*Get a lock on the first directory*/
fileLock=Lock(startingDir,ACCESS_READ);
if(fileLock==NULL)
return(FIND_CONTINUE);
/*And start the find*/
result=doFileFind(fileLock,patResult,recur);
/*We're done, so unlock the lock on the starting directory*/
UnLock(fileLock);
/*And return the result of the search (quit or continue)*/
return(result);
}
char findFileName[256]; // Needs to be extern
/*This is the recursive part of the file-search process. It goes through*/
/*each file, checking to see if a name matches the given literal/pattern.*/
/*If a directory is found, and if the user specified directory recursion,*/
/*we call doFileFind(), giving it a lock on the subdirectory to search.*/
FindStat doFileFind(BPTR startLock,char *pattern,BOOL recur)
{
struct TagItem tag;
struct FileInfoBlock *curFib;
BPTR oldLock;
BPTR fileLock;
BOOL success;
FindStat result=FIND_CONTINUE;
tag.ti_Tag=TAG_DONE;
tag.ti_Data=0;
/*Allocate a FileInfoBlock to hold the results from Execute()/ExNext().*/
if((curFib=AllocDosObject(DOS_FIB,&tag))!=NULL)
{
/*Make the search directory into the current directory*/
oldLock=CurrentDir(startLock);
/*Get the name of the first directory*/
success=Examine(startLock,curFib);
/*Get the name of the first file/dir in the directory*/
success=ExNext(startLock,curFib);
/*Loop while we keep finding files and the user doesn't abort*/
while(success && result==FIND_CONTINUE)
{
/*Update the pointer, to let the user know we're still alive*/
updateBusyPointer();
/*Get the name of the directory that the file is in*/
NameFromLock(startLock,findFileName,255);
if(findFileName[0]!=(char)0 &&
findFileName[strlen(findFileName)-1]!=':')
strcat(findFileName,"/");
strcat(findFileName,curFib->fib_FileName);
/*If we're doing a wildcard search, check to see if the file-*/
/*name matches the pattern*/
if(Wildcards)
{
if(MatchPatternNoCase(pattern,curFib->fib_FileName))
updateFileList(findFileName,curFib->fib_FileName,
curFib->fib_DirEntryType);
}
else
/*If not, just do a regular string compare*/
if(stricmp(pattern,curFib->fib_FileName)==0)
updateFileList(findFileName,curFib->fib_FileName,
curFib->fib_DirEntryType);
/*Check to see if the user wants to abort, see a filename*/
/*listed, etc.*/
result=checkUserStatus();
/*If this is a directory, and if we can recur into directories,*/
/*and if this is a link to a directory and recuring into that */
/*is OK, and if the user didn't abort, AND if the file isn't */
/*a soft link (in which case we can't tell if its a file or a */
/*directory), then descend into the directory.*/
if(curFib->fib_DirEntryType > 0 && recur && result==FIND_CONTINUE
&& (Links || curFib->fib_DirEntryType != ST_LINKDIR)
&& (curFib->fib_DirEntryType != ST_SOFTLINK))
{
fileLock=Lock(curFib->fib_FileName,SHARED_LOCK);
if(fileLock!=NULL)
result=doFileFind(fileLock,pattern,TRUE);
UnLock(fileLock);
}
else
numFiles++;
/*Get the next file/dir name*/
success=ExNext(startLock,curFib);
}
/*We're done, so restore the current directory to it's entry value*/
CurrentDir(oldLock);
/*Free the FileInfoBlock that was allocated*/
FreeDosObject(DOS_FIB,curFib);
}
/*Return the result of the search*/
return(result);
}
/*This handles closing libraries and exiting. It will only close those*/
/*libraries that were actually opened.*/
void cleanup(ULONG err)
{
if(IntuitionBase!=NULL)
CloseLibrary((struct Library *)IntuitionBase);
if(GfxBase!=NULL)
CloseLibrary((struct Library *)GfxBase);
if(GadToolsBase!=NULL)
CloseLibrary(GadToolsBase);
if(AslBase!=NULL)
CloseLibrary(AslBase);
if(WorkbenchBase!=NULL)
CloseLibrary(WorkbenchBase);
if(IFFParseBase!=NULL)
CloseLibrary(IFFParseBase);
exit(err);
}
/*****************************************************************************/
/* The next section is the code that handles computer-human interaction */
/*****************************************************************************/
/*This code handles input before a search takes place*/
/*It returns TRUE if the user wants to start a search, or FALSE if she wants*/
/*to quit*/
BOOL getUserSelections(void)
{
struct IntuiMessage *mesg;
ULONG class;
UWORD code;
struct Gadget *gad;
char dirName[256];
struct TagItem tags[2];
ULONG sigbit;
struct AppMessage *amsg;
tags[0].ti_Tag=GTCB_Checked;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
/*Loop until we return*/
while(TRUE)
{
/*Wait for input*/
if(appWdw!=NULL)
sigbit=Wait(1<<Project0Wnd->UserPort->mp_SigBit|1<<appMsgPort->mp_SigBit);
else
sigbit=Wait(1<<Project0Wnd->UserPort->mp_SigBit);
/*Is it a non-AppWindow event?*/
if(sigbit & (1<<Project0Wnd->UserPort->mp_SigBit))
{
/*Get the message*/
mesg=GT_GetIMsg(Project0Wnd->UserPort);
/*Loop while messages are forthcoming*/
while(mesg!=NULL)
{
class=mesg->Class;
code=mesg->Code;
gad=(struct Gadget *)mesg->IAddress;
GT_ReplyIMsg(mesg);
/*Determine what class of message was received*/
switch(class)
{
/*Window close*/
case IDCMP_CLOSEWINDOW:
return(FALSE);
/*Menu choice*/
case IDCMP_MENUPICK:
if(!handleMenuInput(code))
return(FALSE);
break;
/*Gadget press*/
case IDCMP_GADGETUP:
switch(gad->GadgetID)
{
/*The three checkbox gadgets*/
case GD_Recur:
tags[0].ti_Tag=GA_Disabled;
if(Recur=!Recur)
tags[0].ti_Data=FALSE;
else
tags[0].ti_Data=TRUE;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Links],
Project0Wnd,NULL, tags);
tags[0].ti_Tag=GTCB_Checked;
break;
case GD_Links:
Links=!Links;
break;
case GD_Wildcards:
Wildcards=!Wildcards;
break;
/*This activates the 'Directory' string gadget when*/
/*the user presses 'RETURN' while in the 'Search for'*/
/*gadget.*/
case GD_Pattern:
ActivateGadget(Project0Gadgets[GD_Dir],Project0Wnd,NULL);
break;
/*The browse gadget*/
case GD_Browse:
/*Copy the current 'Directory' string into*/
/*a buffer to give to the file requester*/
strcpy(dirName,((struct StringInfo *)
(Project0Gadgets[GD_Dir]->SpecialInfo))->Buffer);
/*Call the file requester (the NULL means that we */
/*don't want a filename returned, just a directory*/
browse("Please select a directory",dirName,NULL);
/*Place the directory name into the string gadget*/
tags[0].ti_Tag=GTST_String;
tags[0].ti_Data=(ULONG)dirName;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Dir],
Project0Wnd,NULL, tags);
/*Restore this value to this array position, so that*/
/*the VANILLAKEY toggles below don't have to worry*/
/*about setting it*/
tags[0].ti_Tag=GTCB_Checked;
break;
/*The user made a selection from the file list. Fill*/
/*the directory component list with appropriate info.*/
case GD_FileList:
putInDirList(code);
break;
/*Start the search*/
case GD_Go:
return(TRUE);
break;
}
break;
/*Keyboard gadget equivalents*/
case IDCMP_VANILLAKEY:
switch(code)
{
/*Browse, same as above*/
case 'r':
case 'R':
strcpy(dirName,((struct StringInfo *)
(Project0Gadgets[GD_Dir]->SpecialInfo))->Buffer);
browse("Please select a directory",dirName,NULL);
tags[0].ti_Tag=GTST_String;
tags[0].ti_Data=(ULONG)dirName;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Dir],
Project0Wnd,NULL, tags);
tags[0].ti_Tag=GTCB_Checked;
break;
/*Search for*/
case 'f':
case 'F':
ActivateGadget(Project0Gadgets[GD_Pattern],Project0Wnd,
NULL);
break;
/*Directory*/
case 'd':
case 'D':
ActivateGadget(Project0Gadgets[GD_Dir],Project0Wnd,NULL);
break;
/*Go*/
case 'g':
case 'G':
return(TRUE);
/*Subdirectory recursion toggle*/
case 'b':
case 'B':
tags[0].ti_Data=(Recur=!Recur);
GT_SetGadgetAttrsA(Project0Gadgets[GD_Recur],
Project0Wnd,NULL, tags);
tags[0].ti_Tag=GA_Disabled;
if(Recur)
tags[0].ti_Data=FALSE;
else
tags[0].ti_Data=TRUE;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Links],
Project0Wnd,NULL, tags);
tags[0].ti_Tag=GTCB_Checked;
break;
/*'Descend into links' toggle*/
case 'l':
case 'L':
if(Recur)
{
tags[0].ti_Data=(Links=!Links);
GT_SetGadgetAttrsA(Project0Gadgets[GD_Links],
Project0Wnd,NULL, tags);
}
break;
/*'Treat "Search for" as pattern' toggle*/
case 'w':
case 'W':
tags[0].ti_Data=(Wildcards=!Wildcards);
GT_SetGadgetAttrsA(Project0Gadgets[GD_Wildcards],
Project0Wnd,NULL, tags);
break;
}
break;
}
/*Get the next input event*/
mesg=GT_GetIMsg(Project0Wnd->UserPort);
}
}
/*Check to see if this was an AppWindow event*/
if(sigbit & (1<<appMsgPort->mp_SigBit))
{
BPTR dirLock;
/*Loop while there are AppWindow events, although if the user*/
/*drags multiple icons into the window at once, only the first*/
/*one will be used*/
while((amsg=(struct AppMessage *)GetMsg(appMsgPort))!=NULL)
{
/*Get the lock associated with the directory of the icon*/
dirLock=amsg->am_ArgList[0].wa_Lock;
/*Get the directory name*/
NameFromLock(dirLock,dirName,255);
/*Place that directory name into the 'Directory' string gadget*/
tags[0].ti_Tag=GTST_String;
tags[0].ti_Data=(ULONG)dirName;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Dir],
Project0Wnd,NULL, tags);
tags[0].ti_Tag=GTCB_Checked;
/*Reply to the AppWindow message*/
ReplyMsg((struct Message *)amsg);
}
}
}
}
/*Prepare window gadgets for the start of a search*/
void disableWindowGadgets(void)
{
struct TagItem tags[2];
UBYTE gad;
tags[0].ti_Tag=GA_Disabled;
tags[0].ti_Data=TRUE;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=0;
/*Disable each gadget, except for 'Stop' (which is already disabled)*/
for(gad=0;gad<10;gad++)
{
/*and the two listview gadgets (the file and dir lists), since*/
/*they can't be disabled*/
if(gad==GD_FileList)
gad+=2;
GT_SetGadgetAttrsA(Project0Gadgets[gad],Project0Wnd,NULL,tags);
}
/*Enable the 'Stop' gadget*/
tags[0].ti_Data=FALSE;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Stop],Project0Wnd,NULL,tags);
}
/*The inverse of disableWindowGadgets(), called when a search is complete*/
void enableWindowGadgets(void)
{
struct TagItem tags[2];
UBYTE gad;
tags[0].ti_Tag=GA_Disabled;
tags[0].ti_Data=FALSE;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=0;
/*Enable all gadgets except for the listviews and Stop gadget*/
for(gad=0;gad<10;gad++)
{
if(gad==GD_FileList)
gad+=2;
if(gad!=GD_Links || Recur)
GT_SetGadgetAttrsA(Project0Gadgets[gad],Project0Wnd,NULL,tags);
}
/*Disable the 'Stop' gadget*/
tags[0].ti_Data=TRUE;
GT_SetGadgetAttrsA(Project0Gadgets[GD_Stop],Project0Wnd,NULL,tags);
}
/*Get user input while a search is progressing*/
FindStat checkUserStatus(void)
{
struct IntuiMessage *mesg;
ULONG class;
UWORD code;
struct Gadget *gad;
/*Get a message, if one exists (we don't Wait() since we want to return*/
/*immediately if we don't get input*/
mesg=GT_GetIMsg(Project0Wnd->UserPort);
while(mesg!=NULL)
{
class=mesg->Class;
code=mesg->Code;
gad=(struct Gadget *)mesg->IAddress;
GT_ReplyIMsg(mesg);
switch(class)
{
/*Gadget release; it can only be one of two*/
case IDCMP_GADGETUP:
switch(gad->GadgetID)
{
/*Abort the search*/
case GD_Stop:
return(FIND_STOP);
/*Put the directory components of the chosen filename into*/
/*the directory list*/
case GD_FileList:
putInDirList(code);
break;
break;
}
/*The keyboard equivalent of 'Stop'*/
case IDCMP_VANILLAKEY:
if(code=='s' || code=='S')
return(FIND_STOP);
break;
/*Menu selections*/
/*Needs to be reworked*/
case IDCMP_MENUPICK:
if(!handleMenuInput(code))
return(FIND_CLOSE);
break;
/*Close gadget*/
case IDCMP_CLOSEWINDOW:
return(FIND_CLOSE);
}
/*Get the next message*/
mesg=GT_GetIMsg(Project0Wnd->UserPort);
}
/*If we've reached this point, the user hasn't pressed 'Stop', so */
/*continue searching*/
return(FIND_CONTINUE);
}
/*Tags for the file requester*/
struct TagItem fileReqTags[8]=
{
{ASL_Hail,NULL},
{ASL_Height,193},
{ASL_Width,200},
{ASL_TopEdge,5},
{ASL_LeftEdge,10},
{ASL_Dir,NULL},
{ASL_File,NULL},
{TAG_DONE,NULL}
};
/*This function brings up a file requester*/
/*(hail==The title of the requester window)*/
BOOL browse(char *hail,char *dir,char *name)
{
BOOL stat;
struct FileRequester *fr;
fileReqTags[0].ti_Data=(ULONG)hail;
fileReqTags[5].ti_Data=(ULONG)dir;
fileReqTags[6].ti_Data=(ULONG)name;
/*Open the requester*/
if((fr=(struct FileRequester *)AllocAslRequest(ASL_FileRequest,
fileReqTags))!=NULL)
{
/*If the user didn't click on CANCEL*/
if(stat=AslRequest(fr,NULL))
{
/*If the user wants the directory name, return it*/
if(dir!=NULL)
strcpy(dir,fr->rf_Dir);
/*Likewise for the filename*/
if(name!=NULL)
strcpy(name,fr->rf_File);
}
/*Delete the file requester structure*/
FreeAslRequest(fr);
}
return(stat);
}
BOOL handleMenuInput(UWORD menuNumber)
{
while(menuNumber!=MENUNULL)
{
if(MENUNUM(menuNumber)==0)
{
switch(ITEMNUM(menuNumber))
{
case 0:
if(fileList!=NULL &&
getItem(fileList,0)!=NULL)
saveFileList(SUBNUM(menuNumber)==0);
else
printError("There is no list to save",NULL,NULL);
break;
case 2:
printError("FindFile V1.01","August 30, 1992",
"©1992 Dave Schreiber");
break;
case 4:
return(FALSE);
}
}
else
if(ITEMNUM(menuNumber)==0)
{
if(SUBNUM(menuNumber)==0)
copyNameToClipboard(TRUE);
else
copyNameToClipboard(FALSE);
}
else
if(SUBNUM(menuNumber)==0)
clipFileList(TRUE);
else
clipFileList(FALSE);
menuNumber=((struct MenuItem *)ItemAddress(Project0Menus,menuNumber))->NextSelect;
}
return(TRUE);
}
/*****************************************************************************/
/* The next section handles the file and directory lists */
/*****************************************************************************/
/*Intialize the file list*/
void initFileList(void)
{
/*This will delete an old file list, if one exists*/
deleteFileList();
/*Create a new list*/
initList(&fileList);
return;
}
/*Add a name to the file list*/
void updateFileList(char *name,char *nameOnly,LONG dirEntryType)
{
struct TagItem tags[2];
char prefixedName[40];
tags[0].ti_Tag=GTLV_Labels;
tags[0].ti_Data=~0L;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
switch(dirEntryType)
{
case ST_USERDIR:
strcpy(prefixedName,"(dir) ");
break;
case ST_LINKDIR:
strcpy(prefixedName,"<hld> ");
break;
case ST_SOFTLINK:
strcpy(prefixedName,"<sl> ");
break;
case ST_LINKFILE:
strcpy(prefixedName,"<hl> ");
break;
default:
strcpy(prefixedName," ");
break;
}
strcat(prefixedName,nameOnly);
/*Update the list*/
Forbid();
addItem(fileList,name,prefixedName,TRUE);
Permit();
/*Inform Intuition/Gadtools of the change*/
tags[0].ti_Data=(ULONG)fileList;
GT_SetGadgetAttrsA(Project0Gadgets[GD_FileList], Project0Wnd,NULL, tags);
return;
}
/*Delete the file list, if one exists*/
void deleteFileList(void)
{
struct TagItem tags[2];
tags[0].ti_Tag=GTLV_Labels;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
/*If there is a list*/
if(fileList!=NULL)
{
tags[0].ti_Data=0L;
/*Detach the list from the file listview gadget*/
GT_SetGadgetAttrsA(Project0Gadgets[GD_FileList], Project0Wnd,NULL, tags);
/*Delete the list itself*/
freeList(&fileList);
}
return;
}
/*Put a filename into the directory listview*/
void putInDirList(UWORD code)
{
dosNameNode *name;
char filename[256];
char part[36];
char finalPart[40];
char *currentPart;
int s=0;
struct TagItem tags[2];
BOOL first=TRUE;
currentFilename=code;
tags[0].ti_Tag=GTLV_Labels;
tags[0].ti_Data=~0L;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
/*Delete a previous directory component list, if one exists*/
deleteDirList();
/*Initialize a new list*/
initList(&dirList);
/*Get the node corresponding to the name that the user selected*/
name=getItem(fileList,code);
/*Get the filename*/
strcpy(filename,name->fullFilename);
/*This pointer points to the part of the filename that we're currently*/
/*working on*/
currentPart=filename;
/*Loop until we run out of filename*/
while(*currentPart!=0)
{
s=0;
/*Copy a filename component to 'part'*/
do
{
part[s++]=*currentPart++;
}
while(part[s-1]!=':' && part[s-1]!='/' && part[s-1]!=0);
/*If the component ends with a 0, it is the actual filename*/
if(part[s-1]==0)
{
currentPart--;
/*Indent 2 spaces*/
strcpy(finalPart," ");
strcat(finalPart,&name->node.ln_Name[STARTOFNAME]);
}
/*Ends with a ':'? Its the device name (no indent)*/
else if(part[s-1]==':')
{
part[s]=0;
strcpy(finalPart,part);
}
/*Otherwise, ending with a slash==directory name*/
else if(part[s-1]=='/')
{
part[s-1]=0;
/*Indent with one space*/
strcpy(finalPart," ");
strcat(finalPart,part);
}
/*If this isn't the first item in the list, detach the list from the*/
/*dirlist listview*/
if(!first)
GT_SetGadgetAttrsA(Project0Gadgets[GD_DirList], Project0Wnd,NULL, tags);
else
first=FALSE;
/*Add the item to the list*/
addItem(dirList,finalPart,NULL,FALSE);
tags[0].ti_Data=(ULONG)dirList;
/*Update the listview*/
GT_SetGadgetAttrsA(Project0Gadgets[GD_DirList], Project0Wnd,NULL, tags);
}
return;
}
/*Delete the directory component list, if it exists*/
void deleteDirList(void)
{
struct TagItem tags[2];
tags[0].ti_Tag=GTLV_Labels;
tags[0].ti_Data=0L;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
if(dirList!=NULL)
{
/*Detach the list from the listview*/
GT_SetGadgetAttrsA(Project0Gadgets[GD_DirList], Project0Wnd,NULL, tags);
/*And delete it*/
freeList(&dirList);
}
return;
}
/*****************************************************************************/
/* This code handles error and status reporting */
/*****************************************************************************/
struct EasyStruct errorReq=
{
sizeof(struct EasyStruct),
0,
"Program Request...",
NULL,
"Ok"
};
/*The three possible formatting strings*/
char *oneLine="%s";
char *twoLine="%s\n%s";
char *threeLine="%s\n%s\n%s";
/*Print a one, two, or three line error message in an EasyRequester*/
void printError(char *first,char *second,char *third)
{
APTR args[4];
args[0]=args[3]=NULL;
/*Three lines*/
if(third!=NULL)
{
args[2]=third;
args[1]=second;
args[0]=first;
errorReq.es_TextFormat=threeLine;
}
/*Two lines*/
else if(second!=NULL)
{
args[1]=second;
args[0]=first;
errorReq.es_TextFormat=twoLine;
}
/*One line*/
else if(first!=NULL)
{
args[0]=first;
errorReq.es_TextFormat=oneLine;
}
/*Put up the requester*/
EasyRequestArgs(NULL,&errorReq,NULL,args);
return;
}
/*Copy the pointer imagery from a buffer holding Gadget Image style image data*/
/*to a chip memory buffer that will hold the images in the interleaved format*/
/*required by the Amiga's sprite machinery*/
void setupPointerBuffers(void)
{
UBYTE pointer,value;
/*For each of the four pointer animation 'frames'*/
for(pointer=0;pointer<4;pointer++)
{
/*Initialize the required 0 at the beginning and end of the sprite data*/
pointerData[pointer][0]=pointerData[pointer][1]=0;
pointerData[pointer][28]=pointerData[pointer][29]=0;
/*Copy the data over*/
for(value=0;value<13;value++)
{
pointerData[pointer][2*value+2]=PointerImageData[pointer][value];
pointerData[pointer][2*value+3]=PointerImageData[pointer][value+13];
}
}
return;
}
/*Set the pointer to 'frame' 0 of the busy-pointer animation*/
void setBusyPointer(void)
{
pointerCount=0;
SetPointer(Project0Wnd,pointerData[0],13,10,-1,0);
return;
}
/*Advance to the next 'frame' of the pointer animation*/
void updateBusyPointer()
{
/*If at the end, loop back*/
if(++pointerCount==4)
pointerCount=0;
SetPointer(Project0Wnd,pointerData[pointerCount],13,10,-1,0);
return;
}
/*Remove the busy-pointer animation and restore the system pointer*/
void restorePointer()
{
ClearPointer(Project0Wnd);
return;
}
/*****************************************************************************/
/* The next section handles clipboard I/O */
/*****************************************************************************/
struct IFFHandle *iff=NULL;
struct ContextNode *cn;
/*Open the clipboard and create an iffparse.library parsing instance to*/
/*be used for communication with the clipboard (all data is written out*/
/*in FTXT format.*/
/*Returns TRUE if successful, FALSE if not*/
BOOL openClipboard(UBYTE unit)
{
/*Get the IFF handle*/
if((iff=(struct IFFHandle *)AllocIFF())!=NULL)
{
/*Open the clipboard*/
if((iff->iff_Stream=(ULONG)OpenClipboard(unit))!=NULL)
{
/*Initialize the IFF handle*/
InitIFFasClip(iff);
/*and open it*/
if(OpenIFF(iff,IFFF_WRITE)==0)
{
/*Create a 'FORM FTXT' header*/
if(PushChunk(iff,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN)==0)
{
/*Create a 'CHRS' chunk*/
if(PushChunk(iff,0,ID_CHRS,IFFSIZE_UNKNOWN)==0)
return(TRUE);
PopChunk(iff);
}
CloseIFF(iff);
}
CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
}
FreeIFF(iff);
}
return(FALSE);
}
/*Write a given string to the clipboard*/
void writeStringToClipboard(char *string,ULONG stringLen)
{
if(stringLen==~0)
WriteChunkBytes(iff,string,strlen(string));
else
WriteChunkBytes(iff,string,stringLen);
return;
}
/*Close the clipboard*/
void closeClipboard(void)
{
PopChunk(iff);
PopChunk(iff);
CloseIFF(iff);
CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
FreeIFF(iff);
return;
}
/*Copy the currently selected filename to the clipboard*/
void copyNameToClipboard(BOOL full)
{
dosNameNode *name;
/*If there is a current filename...*/
if(currentFilename!=~0)
{
/*Get the name*/
name=getItem(fileList,currentFilename);
/*IF the clipboard was opened successfully*/
if(openClipboard(0))
{
/*Write the full path name*/
if(full)
writeStringToClipboard(name->fullFilename,~0L);
else
/*Or just the filename*/
writeStringToClipboard(&name->node.ln_Name[STARTOFNAME],~0L);
/*Close the clipboard*/
closeClipboard();
}
}
return;
}
/*Send the entire file list to the clipboard*/
void clipFileList(BOOL full)
{
dosNameNode *filename=(dosNameNode *)fileList->lh_Head;
if(filename==NULL)
return;
/*Open the clipboard*/
if(openClipboard(0))
{
/*For each name in the list*/
while(filename->node.ln_Succ!=NULL)
{
/*Write either the*/
if(full)
/*Full directory path*/
writeStringToClipboard(filename->fullFilename,~0);
else
/*Or just the filename*/
writeStringToClipboard(&filename->node.ln_Name[STARTOFNAME],~0);
/*End each line with a line feed*/
writeStringToClipboard("\n",1);
/*Get the next filename*/
filename=(dosNameNode *)filename->node.ln_Succ;
}
/*Close the clipboard*/
closeClipboard();
}
return;
}
/*****************************************************************************/
/* The next section is the code that handles disk I/O */
/*****************************************************************************/
static char saveDirName[256]={NULL};
static char saveFilename[36]={NULL};
/*This function save a file list to a file*/
void saveFileList(BOOL full)
{
char fullFilename[256];
dosNameNode *filename;
BPTR filePointer;
BOOL stat;
/*Get the filename*/
stat=browse("Please select a filename",saveDirName,saveFilename);
/*If we didn't get a name, or the user pressed CANCEL, or there is no*/
/*filelist, return*/
if(saveFilename[0]==0 || !stat || (fileList==NULL))
return;
/*Create the full filename*/
strcpy(fullFilename,saveDirName);
if(fullFilename[strlen(fullFilename)-1]!=':' && fullFilename[0]!=0)
strcat(fullFilename,"/");
strcat(fullFilename,saveFilename);
/*Get the first item in the file list*/
filename=getItem(fileList,0);
/*Open the file*/
if((filePointer=Open(fullFilename,MODE_NEWFILE))!=NULL)
{
/*Loop through each filename*/
while(filename->node.ln_Succ!=NULL)
{
/*Write out either the */
if(full)
/*Full pathname*/
Write(filePointer,filename->fullFilename,strlen(filename->fullFilename));
else
/*Or just the filename*/
Write(filePointer,&filename->node.ln_Name[STARTOFNAME+1],
strlen(filename->node.ln_Name)-STARTOFNAME);
/*Append with a carrage return*/
Write(filePointer,"\n",1);
/*Get the next node*/
filename=(dosNameNode *)filename->node.ln_Succ;
}
/*Close the file*/
Close(filePointer);
}
return;
}
/*End of FF.c*/